home *** CD-ROM | disk | FTP | other *** search
- /* housekeeping.c -- Generally editor fiddly stuff
- Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
-
- This file is part of Jade.
-
- Jade is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- Jade is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Jade; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include "jade.h"
- #include "jade_protos.h"
-
- _PR void adjust_marks_add_x(TX *, long, long, long);
- _PR void adjust_marks_sub_x(TX *, long, long, long);
- _PR void adjust_marks_add_y(TX *, long, long);
- _PR void adjust_marks_sub_y(TX *, long, long);
- _PR void adjust_marks_split_y(TX *, long, long);
- _PR void adjust_marks_join_y(TX *, long, long);
- _PR void resync_xy(VW *);
- _PR void set_start_col(VW *, long);
- _PR void set_start_line(VW *, long);
- _PR void reset_all_views(TX *);
-
- /* The next few routines deal with updating the various references to
- coordinates throughout the views after chunks have been deleted and
- inserted. */
-
- void
- adjust_marks_add_x(TX *tx, long addx, long xpos, long ypos)
- {
- VW *thisvw;
- Mark *thismark;
-
- #define UPD(x,y) \
- do { \
- if((y == ypos) && (x >= xpos)) \
- x += addx; \
- } while(0)
-
- for(thisvw = view_chain; thisvw; thisvw = thisvw->vw_Next)
- {
- if(thisvw->vw_Tx == tx)
- {
- UPD(thisvw->vw_CursorPos.pos_Col, thisvw->vw_CursorPos.pos_Line);
- if(!(thisvw->vw_Flags & VWFF_RECTBLOCKS))
- {
- UPD(thisvw->vw_BlockS.pos_Col, thisvw->vw_BlockS.pos_Line);
- UPD(thisvw->vw_BlockE.pos_Col, thisvw->vw_BlockE.pos_Line);
- }
- }
- }
- for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
- {
- UPD(VPOS(thismark->mk_Pos).pos_Col, VPOS(thismark->mk_Pos).pos_Line);
- }
- UPD(tx->tx_SavedCPos.pos_Col, tx->tx_SavedCPos.pos_Line);
- UPD(tx->tx_SavedWPos.pos_Col, tx->tx_SavedWPos.pos_Line);
- UPD(tx->tx_SavedBlockPos[0].pos_Col, tx->tx_SavedBlockPos[0].pos_Line);
- UPD(tx->tx_SavedBlockPos[1].pos_Col, tx->tx_SavedBlockPos[1].pos_Line);
- #if 1
- if((tx->tx_ModStart.pos_Line == ypos) && (tx->tx_ModStart.pos_Col > xpos))
- tx->tx_ModStart.pos_Col += addx;
- #else
- UPD(tx->tx_ModStart.pos_Col, tx->tx_ModStart.pos_Line);
- #endif
- UPD(tx->tx_ModEnd.pos_Col, tx->tx_ModEnd.pos_Line);
-
- #undef UPD
- }
-
- void
- adjust_marks_sub_x(TX *tx, long subx, long xpos, long ypos)
- {
- VW *thisvw;
- Mark *thismark;
-
- #define UPD(x,y) \
- do { \
- if((y == ypos) && (x >= xpos)) \
- { \
- if((x -= subx) < xpos) \
- x = xpos; \
- } \
- } while(0)
-
- for(thisvw = view_chain; thisvw; thisvw = thisvw->vw_Next)
- {
- if(thisvw->vw_Tx == tx)
- {
- UPD(thisvw->vw_CursorPos.pos_Col, thisvw->vw_CursorPos.pos_Line);
- if(!(thisvw->vw_Flags & VWFF_RECTBLOCKS))
- {
- UPD(thisvw->vw_BlockS.pos_Col, thisvw->vw_BlockS.pos_Line);
- UPD(thisvw->vw_BlockE.pos_Col, thisvw->vw_BlockE.pos_Line);
- }
- }
- }
- for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
- {
- UPD(VPOS(thismark->mk_Pos).pos_Col, VPOS(thismark->mk_Pos).pos_Line);
- }
- UPD(tx->tx_SavedCPos.pos_Col, tx->tx_SavedCPos.pos_Line);
- UPD(tx->tx_SavedWPos.pos_Col, tx->tx_SavedWPos.pos_Line);
- UPD(tx->tx_SavedBlockPos[0].pos_Col, tx->tx_SavedBlockPos[0].pos_Line);
- UPD(tx->tx_SavedBlockPos[1].pos_Col, tx->tx_SavedBlockPos[1].pos_Line);
-
- UPD(tx->tx_ModStart.pos_Col, tx->tx_ModStart.pos_Line);
- #if 1
- if((tx->tx_ModEnd.pos_Line == ypos) && (tx->tx_ModEnd.pos_Col > xpos))
- {
- if((tx->tx_ModEnd.pos_Col -= subx) < xpos)
- tx->tx_ModEnd.pos_Col = xpos;
- }
- #else
- UPD(tx->tx_ModEnd.pos_Col, tx->tx_ModEnd.pos_Line);
- #endif
-
- #undef UPD
- }
-
- /*
- * Whole lines only please
- */
- void
- adjust_marks_add_y(TX *tx, long addy, long ypos)
- {
- VW *thisvw;
- Mark *thismark;
-
- #define UPD(y) \
- do { \
- if(y >= ypos) \
- y += addy; \
- } while(0)
-
- for(thisvw = view_chain; thisvw; thisvw = thisvw->vw_Next)
- {
- if(thisvw->vw_Tx == tx)
- {
- UPD(thisvw->vw_CursorPos.pos_Line);
- UPD(thisvw->vw_BlockS.pos_Line);
- UPD(thisvw->vw_BlockE.pos_Line);
- if(thisvw != curr_vw)
- UPD(thisvw->vw_StartLine);
- }
- }
- for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
- {
- UPD(VPOS(thismark->mk_Pos).pos_Line);
- }
- UPD(tx->tx_SavedCPos.pos_Line);
- UPD(tx->tx_SavedWPos.pos_Line);
- UPD(tx->tx_SavedBlockPos[0].pos_Line);
- UPD(tx->tx_SavedBlockPos[1].pos_Line);
-
- #if 0
- #if 1
- if(tx->tx_ModStart.pos_Line > ypos)
- tx->tx_ModStart.pos_Line += addy;
- #else
- UPD(tx->tx_ModStart.pos_Line);
- #endif
- UPD(tx->tx_ModEnd.pos_Line);
- #endif
-
- #undef UPD
- }
-
- /*
- * Whole lines only please
- */
- void
- adjust_marks_sub_y(TX *tx, long suby, long ypos)
- {
- VW *thisvw;
- Mark *thismark;
-
- #define UPD(y) \
- do { \
- if(y > ypos) \
- { \
- if((y -= suby) < ypos) \
- y = ypos; \
- } \
- } while(0)
-
- #define UPD2(x,y) \
- if(y >= ypos) \
- { \
- if((y -= suby) < ypos) \
- { \
- y = ypos; \
- x = 0; \
- } \
- } while(0)
-
- for(thisvw = view_chain; thisvw; thisvw = thisvw->vw_Next)
- {
- if(thisvw->vw_Tx == tx)
- {
- UPD2(thisvw->vw_CursorPos.pos_Col, thisvw->vw_CursorPos.pos_Line);
- if(thisvw->vw_Flags & VWFF_RECTBLOCKS)
- {
- UPD(thisvw->vw_BlockS.pos_Line);
- UPD(thisvw->vw_BlockE.pos_Line);
- }
- else
- {
- UPD2(thisvw->vw_BlockS.pos_Col, thisvw->vw_BlockS.pos_Line);
- UPD2(thisvw->vw_BlockE.pos_Col, thisvw->vw_BlockE.pos_Line);
- }
- if(thisvw != curr_vw)
- UPD(thisvw->vw_StartLine);
- }
- }
- for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
- {
- UPD2(VPOS(thismark->mk_Pos).pos_Col, VPOS(thismark->mk_Pos).pos_Line);
- }
- UPD2(tx->tx_SavedCPos.pos_Col, tx->tx_SavedCPos.pos_Line);
- UPD2(tx->tx_SavedWPos.pos_Col, tx->tx_SavedWPos.pos_Line);
- UPD2(tx->tx_SavedBlockPos[0].pos_Col, tx->tx_SavedBlockPos[0].pos_Line);
- UPD2(tx->tx_SavedBlockPos[1].pos_Col, tx->tx_SavedBlockPos[1].pos_Line);
-
- UPD2(tx->tx_ModStart.pos_Col, tx->tx_ModStart.pos_Line);
- #if 1
- if(tx->tx_ModEnd.pos_Line > ypos)
- {
- if((tx->tx_ModEnd.pos_Line -= suby) < ypos)
- {
- tx->tx_ModEnd.pos_Line = ypos;
- tx->tx_ModEnd.pos_Col = 0;
- }
- }
- #else
- UPD2(tx->tx_ModEnd.pos_Col, tx->tx_ModEnd.pos_Line);
- #endif
-
- #undef UPD
- #undef UPD2
- }
-
- /*
- * Use when splitting a line into 2, cursor should be at position of split
- */
- void
- adjust_marks_split_y(TX *tx, long xpos, long ypos)
- {
- VW *thisvw;
- Mark *thismark;
-
- #define UPD(y) \
- do { \
- if(y > ypos) \
- y++; \
- } while(0)
-
- #define UPD2(x,y) \
- do { \
- if((y == ypos) && (x >= xpos)) \
- { \
- x -= xpos; \
- y++; \
- } \
- else if(y > ypos) \
- y++; \
- } while(0)
-
- for(thisvw = view_chain; thisvw; thisvw = thisvw->vw_Next)
- {
- if(thisvw->vw_Tx == tx)
- {
- UPD2(thisvw->vw_CursorPos.pos_Col, thisvw->vw_CursorPos.pos_Line);
- if(thisvw->vw_Flags & VWFF_RECTBLOCKS)
- {
- UPD(thisvw->vw_BlockS.pos_Line);
- UPD(thisvw->vw_BlockE.pos_Line);
- }
- else
- {
- UPD2(thisvw->vw_BlockS.pos_Col, thisvw->vw_BlockS.pos_Line);
- UPD2(thisvw->vw_BlockE.pos_Col, thisvw->vw_BlockE.pos_Line);
- }
- if(thisvw != curr_vw)
- UPD(thisvw->vw_StartLine);
- }
- }
- for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
- {
- UPD2(VPOS(thismark->mk_Pos).pos_Col, VPOS(thismark->mk_Pos).pos_Line);
- }
- UPD2(tx->tx_SavedCPos.pos_Col, tx->tx_SavedCPos.pos_Line);
- UPD2(tx->tx_SavedWPos.pos_Col, tx->tx_SavedWPos.pos_Line);
- UPD2(tx->tx_SavedBlockPos[0].pos_Col, tx->tx_SavedBlockPos[0].pos_Line);
- UPD2(tx->tx_SavedBlockPos[1].pos_Col, tx->tx_SavedBlockPos[1].pos_Line);
-
- #if 1
- if((tx->tx_ModStart.pos_Line == ypos) && (tx->tx_ModStart.pos_Col > xpos))
- {
- tx->tx_ModStart.pos_Col -= xpos;
- tx->tx_ModStart.pos_Line++;
- }
- else if(tx->tx_ModStart.pos_Line > ypos)
- tx->tx_ModStart.pos_Line++;
- #else
- UPD2(tx->tx_ModStart.pos_Col, tx->tx_ModStart.pos_Line);
- #endif
- UPD2(tx->tx_ModEnd.pos_Col, tx->tx_ModEnd.pos_Line);
-
- #undef UPD
- #undef UPD2
- }
-
- /*
- * Use when compacting 2 adjacent lines into one
- */
- void
- adjust_marks_join_y(TX *tx, long xpos, long ypos)
- {
- VW *thisvw;
- Mark *thismark;
-
- #define UPD(y) \
- do { \
- if(y > ypos) \
- y--; \
- } while(0)
-
- #define UPD2(x,y) \
- do { \
- if(y > ypos) \
- { \
- if(y == ypos + 1) \
- { \
- x += xpos; \
- y--; \
- } \
- } \
- } while(0)
-
- for(thisvw = view_chain; thisvw; thisvw = thisvw->vw_Next)
- {
- if(thisvw->vw_Tx == tx)
- {
- UPD2(thisvw->vw_CursorPos.pos_Col, thisvw->vw_CursorPos.pos_Line);
- if(thisvw->vw_Flags & VWFF_RECTBLOCKS)
- {
- UPD(thisvw->vw_BlockS.pos_Line);
- UPD(thisvw->vw_BlockE.pos_Line);
- }
- else
- {
- UPD2(thisvw->vw_BlockS.pos_Col, thisvw->vw_BlockS.pos_Line);
- UPD2(thisvw->vw_BlockE.pos_Col, thisvw->vw_BlockE.pos_Line);
- }
- if(thisvw != curr_vw)
- UPD(thisvw->vw_StartLine);
- }
- }
- for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
- {
- UPD2(VPOS(thismark->mk_Pos).pos_Col, VPOS(thismark->mk_Pos).pos_Line);
- }
- UPD2(tx->tx_SavedCPos.pos_Col, tx->tx_SavedCPos.pos_Line);
- UPD2(tx->tx_SavedWPos.pos_Col, tx->tx_SavedWPos.pos_Line);
- UPD2(tx->tx_SavedBlockPos[0].pos_Col, tx->tx_SavedBlockPos[0].pos_Line);
- UPD2(tx->tx_SavedBlockPos[1].pos_Col, tx->tx_SavedBlockPos[1].pos_Line);
-
- UPD2(tx->tx_ModStart.pos_Col, tx->tx_ModStart.pos_Line);
- UPD2(tx->tx_ModEnd.pos_Col, tx->tx_ModEnd.pos_Line);
-
- #undef UPD
- #undef UPD2
- }
-
- /* These routines are called to recalculate the cursor's position on the
- screen... */
- static void
- resync_x(VW *vw)
- {
- long offset;
- calc_cursor_offset(vw);
- offset = vw->vw_LastCursorOffset;
- while((offset - vw->vw_StartCol) >= vw->vw_MaxX)
- {
- vw->vw_StartCol += vw->vw_XStep;
- vw->vw_Flags |= VWFF_FORCE_REFRESH;
- }
- while(offset < vw->vw_StartCol)
- {
- vw->vw_StartCol -= vw->vw_XStep;
- if(vw->vw_StartCol < 0)
- vw->vw_StartCol = 0;
- vw->vw_Flags |= VWFF_FORCE_REFRESH;
- }
- }
-
- static void
- resync_y(VW *vw)
- {
- TX *tx = vw->vw_Tx;
- long y = vw->vw_CursorPos.pos_Line - vw->vw_StartLine;
- if(y < 0)
- {
- if(-y > vw->vw_YStep)
- vw->vw_StartLine = vw->vw_CursorPos.pos_Line - (vw->vw_MaxY / 2);
- else
- vw->vw_StartLine -= vw->vw_YStep;
- if(vw->vw_StartLine < 0)
- vw->vw_StartLine = 0;
- else if(vw->vw_StartLine >= tx->tx_NumLines)
- vw->vw_StartLine = tx->tx_NumLines - 1;
- }
- else if(y >= vw->vw_MaxY)
- {
- if((vw->vw_MaxY + vw->vw_YStep) <= y)
- vw->vw_StartLine = vw->vw_CursorPos.pos_Line - (vw->vw_MaxY / 2);
- else
- vw->vw_StartLine += vw->vw_YStep;
- if(vw->vw_StartLine < 0)
- vw->vw_StartLine = 0;
- else if(vw->vw_StartLine >= tx->tx_NumLines)
- vw->vw_StartLine = tx->tx_NumLines - 1;
- /* Check for a `gap' at the bottom of the display */
- if((tx->tx_NumLines >= vw->vw_MaxY)
- && ((tx->tx_NumLines - vw->vw_StartLine) < vw->vw_MaxY))
- {
- vw->vw_StartLine = tx->tx_NumLines - vw->vw_MaxY;
- }
- }
- }
-
- void
- resync_xy(VW *vw)
- {
- if(vw->vw_Tx != vw->vw_LastRefTx)
- /* kludge */
- vw->vw_LastDisplayOrigin = vw->vw_DisplayOrigin;
- resync_x(vw);
- resync_y(vw);
- }
-
- void
- set_start_col(VW *vw, long col)
- {
- if(vw->vw_StartCol != col)
- {
- vw->vw_Flags |= VWFF_FORCE_REFRESH;
- vw->vw_StartCol = col;
- }
- }
-
- void
- set_start_line(VW *vw, long line)
- {
- long cline = vw->vw_StartLine;
- if(line != cline)
- {
- long yord = vw->vw_CursorPos.pos_Line - cline;
- vw->vw_StartLine = line;
- #if 0
- /* This is done in vert_scroll() now; doing it here as
- well means it's done twice! */
- if(!(vw->vw_Flags & VWFF_FORCE_REFRESH))
- {
- long diff = line - cline;
- if((diff > 0) && (diff <= vw->vw_MaxScroll))
- {
- long ypos = vw->vw_MaxY - 1;
- sys_scroll_vw(vw, diff);
- redraw_lines(vw, cline + ypos, line + ypos + 1);
- }
- else if((diff < 0) && (diff >= -vw->vw_MaxScroll))
- {
- sys_scroll_vw(vw, diff);
- redraw_lines(vw, line, cline);
- }
- else
- vw->vw_Flags |= VWFF_FORCE_REFRESH;
- }
- else
- vw->vw_Flags |= VWFF_FORCE_REFRESH;
- #endif
- vw->vw_CursorPos.pos_Line = line + yord;
- if(vw->vw_CursorPos.pos_Line >= vw->vw_Tx->tx_NumLines)
- vw->vw_CursorPos.pos_Line = vw->vw_Tx->tx_NumLines - 1;
- }
- }
-
- /*
- * This makes all views of this file have their cursor at the top of the
- * file, it also refreshes each view.
- */
- void
- reset_all_views(TX *tx)
- {
- VW *thisvw;
- for(thisvw = view_chain; thisvw; thisvw = thisvw->vw_Next)
- {
- if(thisvw->vw_Tx == tx)
- {
- thisvw->vw_CursorPos.pos_Col = 0;
- thisvw->vw_CursorPos.pos_Line = 0;
- thisvw->vw_StartCol = 0;
- thisvw->vw_StartLine = 0;
- thisvw->vw_BlockStatus = -1;
- thisvw->vw_Flags |= VWFF_FORCE_REFRESH;
- thisvw->vw_Flags &= ~VWFF_MESSAGE;
- std_message(thisvw);
- }
- tx->tx_SavedCPos.pos_Col = 0;
- tx->tx_SavedCPos.pos_Line = 0;
- tx->tx_SavedWPos.pos_Col = 0;
- tx->tx_SavedWPos.pos_Line = 0;
- tx->tx_SavedBlockStatus = -1;
- }
- }
-